#pragma once

#include <algorithm>
#include <climits>
#include <cstddef>
#include <string>
#include <sys/types.h>
#include <vector>

// 网络库底层缓冲去类型
class Buffer {
  public:
    static const size_t kCheapPrepend = 8;
    static const size_t kInitialSize = 1024;

    explicit Buffer(size_t initial_size = kInitialSize)
        : buffer_(kCheapPrepend + initial_size), reader_index_(kCheapPrepend),
          writer_index_((kCheapPrepend)) {}
    size_t readable_bytes() const { return writer_index_ - reader_index_; }

    size_t writable_bytes() const { return buffer_.size() - writer_index_; }

    size_t prependable_bytes() const { return reader_index_; }

    // 返回缓冲区可读数据起始地址
    const char *peek() const { return begin() + reader_index_; }

    // on_message strign <- Buffer
    void retrieve(size_t len) {
        if (len < readable_bytes()) {
            reader_index_ +=
                len; // 应用只读取了刻度缓冲区数据的一部分，就是len,剩下reader_index_ +=len
        } else {     // len == readable_bytes()
            retrieve_all();
        }
    }

    void retrieve_all() { reader_index_ = writer_index_ = kCheapPrepend; }

    // 把on_message函数上报buffer数据，转成string类型的数据返回
    std::string retrieve_all_as_string() {
        return retrieve_as_string(readable_bytes()); // 应用可读取数据的长度
    }

    std::string retrieve_as_string(size_t len) {
        std::string result(peek(), len);
        retrieve(len); // 上面一句话把缓冲区可读的数据，已经读取出来，这里肯定要对缓冲区进行符为操作
        return result;
    }

    // buffer_.size() -write_index_ len
    void ensure_writeable_bytes(size_t len) {
        if (writable_bytes() < len) {
            make_space(len); // 扩容数组
        }
    }

    // 把[data,data+len]内存上的数据，添加到writable缓冲区中
    void append(const char *data, size_t len) {
        ensure_writeable_bytes(len);
        std::copy(data, data + len, begin_write()); // 备份操作，如果第一次空间不够而扩容，这次会搬运
        writer_index_ += len;
    }

    char *begin_write() { return begin() + writer_index_; }

    const char *begin_write() const { return begin() + writer_index_; }

    ssize_t read_fd(int fd, int *save_errno);

    ssize_t write_fd(int fd, int *save_errno);

  private:
    char *begin() {
        return &*buffer_.begin(); // vector底层数组元素的首地址，也是数组起始地址
    }
    const char *begin() const { return &*buffer_.begin(); }
    void make_space(size_t len) {
        if (writable_bytes() + prependable_bytes() < len + kCheapPrepend) {
            buffer_.resize(writer_index_ + len);
        } else {
            size_t readable = readable_bytes();
            std::copy(begin() + reader_index_, begin() + writer_index_, begin() + kCheapPrepend);
            reader_index_ = kCheapPrepend;
            writer_index_ = reader_index_ + readable;
        }
    }
    std::vector<char> buffer_;
    size_t reader_index_;
    size_t writer_index_;
};